package com.wuye.web.repair.controller;

import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.model.GridFSFile;
import com.wuye.utils.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

@Api(tags = "视频控制类")
@RestController
@RequestMapping("/api/video")
public class VideoController {
    @Resource
    private GridFsTemplate gridFsTemplate;
    @Resource
    private GridFSBucket gridFSBucket;

    @ApiOperation("上传视频")
    @PostMapping("/upload")
    public Result upload(MultipartFile video) throws IOException {
        ObjectId videoId;
        InputStream inputStream = video.getInputStream();
        String videoName = video.getOriginalFilename();

        //上传视频并返回id
        videoId = gridFsTemplate.store(inputStream,videoName,video.getContentType());
        inputStream.close();

        Map map = new HashMap<>();
        map.put("videoId",videoId.toString());
        map.put("videoName", videoName);

        return Result.success(map);
    }

    @ApiOperation("根据id删除视频")
    @DeleteMapping("/{videoId}")
    public Result deleteVideo(@PathVariable("videoId") String videoId){
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(videoId));

        gridFsTemplate.delete(query);
        return Result.success();
    }

    @ApiOperation("播放视频")
    @GetMapping("/{videoId}")
    public void viewTo(HttpServletRequest request, HttpServletResponse response, @PathVariable("videoId") String videoId) throws IOException {
        long skip = -1;
        long length = -1;
        Query gridQuery = new Query().addCriteria(Criteria.where("_id").is(new ObjectId(videoId)));

        GridFSFile gridFSFile = gridFsTemplate.findOne(gridQuery);
        response.setHeader("Content-Type", "video/mp4");
        long fileLength = gridFSFile.getLength();
        long end = fileLength - 1;

        String range = request.getHeader("range");
        if (range != null && range.length() > 0){
            int idx = range.indexOf("-");
            skip = Long.parseLong(range.substring(6,idx));
            if ((idx+1) < range.length()){
                end = Long.parseLong(range.substring(idx + 1));
            }
            length = end - skip + 1;
        }

        if (range == null || range.length() <= 0) {//bytes=32523-32523
            response.setHeader("Content-Length", "" + fileLength);
            response.setStatus(200);
        } else {
            response.setHeader("Content-Length", "" + length);
            response.setHeader("Content-Range", "bytes " + skip + "-" + end + "/" + fileLength);
            response.setStatus(206);
        }

        System.out.println("bytes " + skip + "-" + end + "/" + fileLength);

        download(response.getOutputStream(), gridFSFile, skip, length);
    }

    /**
     * 文件下载基础类
     * 断点续读
     * @param outputStream 文件输出流
     * @param gridFSFile   mongo文件
     * @param skip         跳过多少字节 <=0忽略
     * @param length       输出字节长度 <=忽略
     * @throws Exception
     */
    private void download(ServletOutputStream outputStream, GridFSFile gridFSFile, long skip, long length) throws IOException {
        InputStream inputStream = null;

        //打开下载流对象
        GridFSDownloadStream gridFSDownloadStream = gridFSBucket.openDownloadStream(gridFSFile.getObjectId());
        GridFsResource resource = new GridFsResource(gridFSFile,gridFSDownloadStream);
        try {
            inputStream = resource.getInputStream();
            if (skip>0){
                //如果有断点跳过了流的部分内容，则调用输入流的skip方法，跳过变量skip字节的流
                inputStream.skip(skip);
            }
            byte[] bs = new byte[1024];
            int len;
            while ((len = inputStream.read(bs)) != -1){
                if (length > 0){
                    if (length > len){
                        outputStream.write(bs,0,len);
                        outputStream.flush();
                        length -= len;
                    }else {
                        outputStream.write(bs, 0, (int) length);
                        outputStream.flush();
                        break;
                    }
                } else {
                    outputStream.write(bs, 0, len);
                    outputStream.flush();
                }
            }
        } catch (Exception e) {
            throw e;
        } finally {
            if (inputStream != null){
                inputStream.close();
            }
            if (outputStream != null){
                outputStream.close();
            }
        }

    }
}
